﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SoaBox.Business.Entities;
using System.CodeDom;
using System.Reflection;

namespace SoaBox.Business
{
    /// <summary>
    /// Class that generates the classes that are exposes in the facade
    /// </summary>
    public class SoaGenerator
    {

        private CodeMemberMethod GenerateMethods(CodeFieldReferenceExpression fieldReference, MethodData methodData)
        {
            CodeMemberMethod method = new CodeMemberMethod();
            method.Name = methodData.Name;
            method.ReturnType = new CodeTypeReference(methodData.ReturnedType.Name);
            method.Attributes = MemberAttributes.Public;

            // Parameters
            CodeParameterDeclarationExpression[] parameters = GenerateParameters(methodData.Parameters.ToArray());

            method.Parameters.AddRange(parameters);

            CodeExpression[] arguments = GenerateArguments(methodData.Parameters.ToArray());
            
            // Statement					
            CodeMethodInvokeExpression invocation;
            invocation = new CodeMethodInvokeExpression(fieldReference, methodData.Name, arguments);
            
            if (Type.GetType(methodData.ReturnedType.Name) == typeof(void))
            {
                method.Statements.Add(invocation);
            }
            else
            {
                method.Statements.Add(new CodeMethodReturnStatement(invocation));
            }

            return method;
        }

        private CodeParameterDeclarationExpression[] GenerateParameters(ParameterData[] parameters)
        {
            CodeParameterDeclarationExpression[] parameterDeclarations = new CodeParameterDeclarationExpression[parameters.Length];

            for(int i = 0; i < parameters.Length; i++)
            {
                // Parameter
                parameterDeclarations[i] = new CodeParameterDeclarationExpression();
                parameterDeclarations[i].Type = new CodeTypeReference(parameters[i].Type.Name);
                parameterDeclarations[i].Name = parameters[i].Name;
            }

            return parameterDeclarations;
        }

        private CodeExpression[] GenerateArguments(ParameterData[] parameters)
        {
            CodeExpression[] arguments = new CodeExpression[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                // Parameter
                arguments[i] = new CodeVariableReferenceExpression(parameters[i].Name);                
            }

            return arguments;
        }

    }
}
